﻿#region Usings

using System;
using System.Collections.Generic;
using System.Xml.XPath;
using Yandex.Market.Api.Common;
using Yandex.Market.Api.YmlSerialization;

#endregion

namespace Yandex.Market.Api.Model
{
    /// <summary>
    ///   В элементе shop содержится описание магазина и товаров магазина.
    /// </summary>
    [YmlSerializeAs("shop")]
    [Serializable]
    public class Shop
    {
        /// <summary>
        /// </summary>
        public Shop()
        {
            Offers = new List<IOffer>();
            Currencies = new List<Currency>();
            Categories = new List<Category>();
        }

        /// <summary>
        ///   Короткое название магазина — название, которое выводится в списке найденных на Яндекс.Маркете товаров.<br />  
        ///   Оно не должно содержать более 20 символов.<br />  
        ///   В названии нельзя использовать слова, не имеющие отношения к наименованию магазина (например: лучший, дешевый), указывать номер телефона и т.п.<br />
        ///   Название магазина должно совпадать с фактическим названием магазина, которое публикуется на сайте.<br />  
        ///   При несоблюдении данного требования наименование может быть изменено Яндексом самостоятельно без уведомления магазина.<br />
        /// </summary>
        [YmlSerializeAs("name")]
        [YmlElementOrder(0)]
        public string Name { set; get; }

        /// <summary>
        ///   Полное наименование компании, владеющей магазином.<br />  
        ///   Не публикуется, используется для внутренней идентификации.
        /// </summary>
        [YmlSerializeAs("company")]
        [YmlElementOrder(10)]
        public string Company { set; get; }

        /// <summary>
        ///   URL главной страницы магазина
        /// </summary>
        [YmlSerializeAs("url")]
        [YmlElementOrder(20)]
        public string Url { set; get; }

        /// <summary>
        ///   Телефон разработчиков CMS или агентства, осуществляющего техподдержку.
        /// </summary>
        [YmlSerializeAs("phone")]
        [YmlElementOrder(30)]
        public string Phone { get; set; }

        /// <summary>
        ///   Система управления контентом, на основе которой работает магазин (CMS).
        /// </summary>
        [YmlSerializeAs("platform")]
        [YmlElementOrder(40)]
        public string Platform { get; set; }

        /// <summary>
        ///   Версия CMS.
        /// </summary>
        [YmlSerializeAs("version")]
        [YmlElementOrder(50)]
        public string Version { get; set; }

        /// <summary>
        ///   Наименование агентства, которое оказывает техническую поддержку интернет-магазину и отвечает за работоспособность сайта.
        /// </summary>
        [YmlSerializeAs("agency")]
        [YmlElementOrder(60)]
        public string Agency { get; set; }

        /// <summary>
        ///   Контактный адрес разработчиков CMS или агентства, осуществляющего техподдержку.
        /// </summary>
        [YmlCollection(YmlCollectionSerializationTypes.RecursiveWithNoContainingElement, EachElementName = "email")]
        [YmlElementOrder(70)]
        public List<string> Emails { get; set; }

        /// <summary>
        ///   Элемент currencies задает список курсов валют магазина. Каждая из валют описывается отдельным элементом currency.
        /// </summary>
        [YmlCollection(YmlCollectionSerializationTypes.Recursive, EachElementName = "currency")]
        [YmlSerializeAs("currencies")]
        [YmlElementOrder(80)]
        public List<Currency> Currencies { get; set; }

        /// <summary>
        ///   В элементе categories содержится список категорий магазина. Каждая категория описывается отдельным элементом category.
        /// </summary>
        [YmlCollection(YmlCollectionSerializationTypes.Recursive, EachElementName = "category")]
        [YmlSerializeAs("categories")]
        [YmlElementOrder(90)]
        public List<Category> Categories { get; set; }

        /// <summary>
        ///   Наличие точки продаж, где товар можно купить без предварительного заказа, указывается значением true у элемента store. <br />
        ///   Если точки продаж нет, используется значение false.
        /// </summary>
        [YmlSerializeAs("store")]
        [YmlElementOrder(100)]
        public bool? Store { get; set; }

        /// <summary>
        ///   Если предусмотрена возможность предварительно заказать данный товар и забрать его в точке продаж, для элемента используется значение true.<br />
        ///   В противном случае — false.
        /// </summary>
        [YmlSerializeAs("pickup")]
        [YmlElementOrder(110)]
        public bool? Pickup { get; set; }

        ///<summary>
        ///  Элемент, обозначающий возможность доставить соответствующий товар. "false" данный товар не может быть доставлен ("самовывоз").<br />
        ///  "true" товар доставляется на условиях, которые указываются в партнерском интерфейсе http://partner.market.yandex.ru на странице "редактирование".
        ///</summary>
        [YmlSerializeAs("delivery")]
        [YmlElementOrder(120)]
        public bool? Delivery { set; get; }

        /// <summary>
        /// </summary>
        [YmlSerializeAs("deliveryIncluded")]
        [YmlElementOrder(130)]
        public bool? DeliveryIncluded { get; set; }

        /// <summary>
        ///   В элементе local_delivery_cost указывается стоимость доставки для своего региона.
        /// </summary>
        [YmlSerializeAs("local_delivery_cost")]
        [YmlElementOrder(140)]
        public double? LocalDeliveryCost { set; get; }

        /// <summary>
        ///   Элемент обязателен для обозначения товара, имеющего отношение к удовлетворению сексуальных потребностей,<br /> 
        ///   либо иным образом эксплуатирующего интерес к сексу.
        /// </summary>
        [YmlSerializeAs("adult")]
        [YmlElementOrder(150)]
        public bool? Adult { get; set; }

        /// <summary>
        ///   В элементе offers содержится список товарных предложений магазинов. Каждое товарное предложение описывается отдельным элементом offer.
        /// </summary>
        [YmlCollection(YmlCollectionSerializationTypes.Recursive, EachElementName = "offer")]
        [YmlSerializeAs("offers")]
        [YmlElementOrder(160)]
        public List<IOffer> Offers { get; set; }

        internal static Shop CreateShopFromXml(XPathNavigator nav)
        {
            Shop shop = new Shop();
            XPathNavigator node = nav.SelectSingleNode("name");
            if(node != null)
                shop.Name = node.Value;

            node = nav.SelectSingleNode("company");
            if(node != null)
                shop.Company = node.Value;

            node = nav.SelectSingleNode("url");
            if(node != null)
                shop.Url = node.Value;

            node = nav.SelectSingleNode("phone");
            if(node != null)
                shop.Phone = node.Value;

            node = nav.SelectSingleNode("platform");
            if(node != null)
                shop.Platform = node.Value;

            node = nav.SelectSingleNode("version");
            if(node != null)
                shop.Version = node.Value;

            node = nav.SelectSingleNode("agency");
            if(node != null)
                shop.Agency = node.Value;

            XPathNodeIterator iterator = nav.Select("email");
            List<string> emails = new List<string>();
            while(iterator.MoveNext())
            {
                if(iterator.Current != null)
                    emails.Add(iterator.Current.Value);
            }

            if(emails.Count > 0)
                shop.Emails = emails;

            iterator = nav.Select("currencies/currency");
            while(iterator.MoveNext())
            {
                if(iterator.Current != null)
                    shop.Currencies.Add(Currency.CreateCurrencyFromXml(iterator.Current));
            }

            iterator = nav.Select("categories/category");
            while(iterator.MoveNext())
            {
                if(iterator.Current != null)
                    shop.Categories.Add(Category.CreateCategoryFromXml(iterator.Current));
            }

            bool booleanVal;

            node = nav.SelectSingleNode("store");
            if(node != null && Utils.TryParseYmlBoolean(node.Value, out booleanVal))
                shop.Store = booleanVal;

            node = nav.SelectSingleNode("pickup");
            if(node != null && Utils.TryParseYmlBoolean(node.Value, out booleanVal))
                shop.Pickup = booleanVal;

            node = nav.SelectSingleNode("delivery");
            if(node != null && Utils.TryParseYmlBoolean(node.Value, out booleanVal))
                shop.Delivery = booleanVal;

            node = nav.SelectSingleNode("deliveryIncluded");
            if(node != null && Utils.TryParseYmlBoolean(node.Value, out booleanVal))
                shop.DeliveryIncluded = booleanVal;

            double doubleVal;

            node = nav.SelectSingleNode("local_delivery_cost");
            if(node != null && Utils.TryParseYmlDouble(node.Value, out doubleVal))
                shop.LocalDeliveryCost = doubleVal;

            node = nav.SelectSingleNode("adult");
            if(node != null && Utils.TryParseYmlBoolean(node.Value, out booleanVal))
                shop.Adult = booleanVal;

            iterator = nav.Select("offers/offer");
            while(iterator.MoveNext())
            {
                if(iterator.Current != null)
                    shop.Offers.Add(OfferBase.CreateOfferFromXml(iterator.Current));
            }

            return shop;
        }
    }
}